home *** CD-ROM | disk | FTP | other *** search
/ CD Actual 1 / PC Actual CD 01.iso / share / dos / graficos / plydat14.arj / MOUNTAIN.C < prev    next >
Encoding:
C/C++ Source or Header  |  1992-03-29  |  7.6 KB  |  217 lines

  1. /*
  2.  * mountain.c - creates a fractal mountain, using Carpenter's method with a
  3.  *     different extension to square grids.  A pyramid of 4 glass spheres
  4.  *     is added in front of the mountain.  None of the spheres are clipped.
  5.  *     A few of the polygons are clipped.  One light source.
  6.  *
  7.  * Version:  2.2 (11/17/87)
  8.  * Author:  Eric Haines, 3D/Eye, Inc.
  9.  *
  10.  * SIZE_FACTOR determines the number of objects output.
  11.  *     Total triangular polygons = 2 * (4**SIZE_FACTOR)
  12.  *
  13.  *     SIZE_FACTOR     # triangles     # spheres
  14.  *         1                8               4
  15.  *         2               32               4
  16.  *         3              128               4
  17.  *
  18.  *         6             8192               4
  19.  */
  20.  
  21.  
  22. #include <stdio.h>
  23. #include <math.h>
  24. #ifdef MAC
  25. #include <console.h>
  26. #endif
  27. #include "def.h"
  28. #include "lib.h"
  29.  
  30. /* size factor determines number of polygons */
  31. #define SIZE_FACTOR 4
  32.  
  33. /* fractal dimension - affects variance of z.  Between 2 and 3 */
  34. #define FRACTAL_DIMENSION 2.2
  35.  
  36. /* change MOUNTAIN_NO to get a different mountain */
  37. #define MOUNTAIN_NO 21
  38.  
  39. /* lower left corner and width of mountain definitions */
  40. #define X_CORNER  -1.0
  41. #define Y_CORNER  -1.0
  42. #define WIDTH      2.0
  43.  
  44. /* hashing function to get a seed for the random number generator */
  45. #define hash_rand(A,B,C) ( ( ((A)<<(23-(C))) + ((B)<<(15-(C)))\
  46.                             + ((A)<<(7-(C))) ) & 0xffff )
  47.  
  48. static   long    num_pts ;
  49. static  double roughness ;
  50.  
  51. /* create a pyramid of crystal spheres */
  52. static void
  53. create_spheres(COORD4 *center, char *txname)
  54. {
  55.     double  angle ;
  56.     COORD4  axis, new_pt, pt, sphere ;
  57.     long    i ;
  58.     MATRIX  mx ;
  59.  
  60.     SET_COORD( axis, 1.0, 1.0, 0.0 ) ;
  61.     lib_normalize_coord3( &axis ) ;
  62.     angle = acos( (double)( -1.0/3.0 ) ) ;
  63.  
  64.     /* set center of pyramid and radius */
  65.     SET_COORD4( pt, 0.0, 0.0, center->w * sqrt( (double)( 3.0/2.0 ) ), 0.0 ) ;
  66.     COPY_COORD( sphere, pt ) ;
  67.     ADD2_COORD( sphere, *center ) ;
  68.     sphere.w = center->w ;
  69.     lib_output_sphere( &sphere, txname ) ;
  70.     lib_create_axis_rotate_matrix( mx, &axis, angle ) ;
  71.     lib_transform_coord( &new_pt, &pt, mx ) ;
  72.  
  73.     for ( i = 0 ; i < 3 ; ++i ) {
  74.        lib_create_rotate_matrix( mx, Z_AXIS, (double)i * 2.0 * PI / 3.0 ) ;
  75.        lib_transform_coord( &sphere, &new_pt, mx ) ;
  76.        ADD2_COORD( sphere, *center ) ;
  77.        sphere.w = center->w ;
  78.        lib_output_sphere( &sphere, txname ) ;
  79.        }
  80. }
  81.  
  82. /*
  83.  * Build mountain section.  If at width > 1, split quadrilateral into four
  84.  * parts.  Else if at width == 1, output quadrilateral as two triangles.
  85.  */
  86. static void
  87. grow_mountain(long width, long ll_x, long ll_y,
  88.               double ll_fz, double lr_fz, double ur_fz, double ul_fz,
  89.               char *txname)
  90. {
  91.     long    half_width, iz ;
  92.     double  l_fx, r_fx, l_fy, u_fy ;
  93.     double  lower_fz, right_fz, upper_fz, left_fz, middle_fz ;
  94.     long    num_tri, num_tri_vert, num_vert ;
  95.     double  rise_height, hside_length ;
  96.     COORD4  tri_vert[3] ;
  97.  
  98.    if ( width == 1 ) {
  99.       /* calculate x and y coordinates of corners */
  100.       l_fx = X_CORNER + (double)ll_x * WIDTH / (double)num_pts;
  101.       r_fx = X_CORNER + (double)(ll_x+1) * WIDTH / (double)num_pts;
  102.       l_fy = Y_CORNER + (double)ll_y * WIDTH / (double)num_pts;
  103.       u_fy = Y_CORNER + (double)(ll_y+1) * WIDTH / (double)num_pts;
  104.  
  105.       /* output two triangles for section */
  106.       for (num_tri=0;num_tri<2;++num_tri) {
  107.          for (num_vert=0;num_vert<3;++num_vert) {
  108.             num_tri_vert = (num_vert + num_tri * 2) % 4;
  109.             if (num_tri_vert == 0) {
  110.                SET_COORD(tri_vert[num_vert], l_fx, l_fy, ll_fz);
  111.                }
  112.             else if ( num_tri_vert == 1 ) {
  113.                SET_COORD( tri_vert[num_vert], r_fx, l_fy, lr_fz ) ;
  114.                }
  115.             else if ( num_tri_vert == 2 ) {
  116.                SET_COORD( tri_vert[num_vert], r_fx, u_fy, ur_fz ) ;
  117.                }
  118.             else {
  119.                SET_COORD( tri_vert[num_vert], l_fx, u_fy, ul_fz ) ;
  120.                }
  121.             }
  122.          lib_output_polygon( 3, tri_vert, txname) ;
  123.          }
  124.       }
  125.    else {
  126.       /* subdivide edges and move in z direction */
  127.       half_width = width>>1 ;
  128.       hside_length = (double)half_width * WIDTH / (double)num_pts ;
  129.       rise_height = hside_length * roughness ;
  130.  
  131.       /* for each midpoint, find z */
  132.       iz = MOUNTAIN_NO + hash_rand( ll_x + half_width, ll_y, SIZE_FACTOR ) ;
  133.       lower_fz = ( ll_fz + lr_fz ) / 2.0 +
  134.                                     rise_height * lib_gauss_rand( iz ) ;
  135.       iz = MOUNTAIN_NO +
  136.               hash_rand( ll_x + width, ll_y + half_width, SIZE_FACTOR ) ;
  137.       right_fz = ( lr_fz + ur_fz ) / 2.0 +
  138.                                     rise_height * lib_gauss_rand( iz ) ;
  139.       iz = MOUNTAIN_NO +
  140.               hash_rand( ll_x + half_width, ll_y + width, SIZE_FACTOR ) ;
  141.       upper_fz = ( ur_fz + ul_fz ) / 2.0 +
  142.                                     rise_height * lib_gauss_rand( iz ) ;
  143.       iz = MOUNTAIN_NO + hash_rand( ll_x, ll_y + half_width, SIZE_FACTOR ) ;
  144.       left_fz  = (ul_fz + ll_fz ) / 2.0 + rise_height * lib_gauss_rand( iz ) ;
  145.       iz = MOUNTAIN_NO +
  146.           hash_rand( ll_x + half_width, ll_y + half_width, SIZE_FACTOR ) ;
  147.       middle_fz = ( ll_fz + lr_fz + ur_fz + ul_fz ) / 4.0 +
  148.                        1.4142136 * rise_height * lib_gauss_rand( iz ) ;
  149.  
  150.       /* check subsections for subdivision or output */
  151.       grow_mountain(half_width, ll_x, ll_y, ll_fz,
  152.                     lower_fz, middle_fz, left_fz, txname) ;
  153.       grow_mountain(half_width, ll_x+half_width, ll_y, lower_fz,
  154.                     lr_fz, right_fz, middle_fz, txname) ;
  155.       grow_mountain(half_width, ll_x+half_width, ll_y+half_width,
  156.                     middle_fz, right_fz, ur_fz, upper_fz, txname) ;
  157.       grow_mountain(half_width, ll_x, ll_y+half_width,
  158.                     left_fz, middle_fz, upper_fz, ul_fz, txname) ;
  159.  
  160.       }
  161. }
  162.  
  163. void
  164. main(int argc, char *argv[])
  165. {
  166.     COORD4  back_color, obj_color ;
  167.     COORD4  center, light ;
  168.     COORD4  from, at, up, dir;
  169.     double  ratio ;
  170.     char *txname;
  171.  
  172. #ifdef MAC
  173.    argc = ccommand(&argv);
  174. #endif
  175.  
  176.     /* output viewpoint */
  177.     SET_COORD( from, -1.6, 1.6, 1.7 ) ;
  178.     SET_COORD( at, 0.0, 0.0, 0.0 ) ;
  179.     SET_COORD( up, 0.0, 0.0, 1.0 ) ;
  180.     lib_output_viewpoint( &from, &at, &up, 45.0, 0.5, 1.0, 256, 256);
  181.  
  182.     /* output background color - UNC sky blue */
  183.     SET_COORD( back_color, 0.078, 0.361, 0.753 ) ;
  184.     lib_output_background_color( &back_color ) ;
  185.  
  186.     /* output light sources */
  187.     SET_COORD( light, -100.0, -100.0, 100.0 ) ;
  188.     lib_output_light( &light ) ;
  189.  
  190.     /* Output bounding slabs oriented along the coordinate axes */
  191.     SET_COORD(dir, 1.0, 0.0, 0.0);
  192.     lib_output_bounding_slab(&dir);
  193.     SET_COORD(dir, 0.0, 1.0, 0.0);
  194.     lib_output_bounding_slab(&dir);
  195.     SET_COORD(dir, 0.0, 0.0, 1.0);
  196.     lib_output_bounding_slab(&dir);
  197.  
  198.     /* set up crystal sphere color - clear white */
  199.     SET_COORD( obj_color, 1.0, 1.0, 1.0 ) ;
  200.     txname = lib_output_color( &obj_color, 0.0, 0.1, 0.9, 2.0, 0.0, 0.9, 1.5 ) ;
  201.  
  202.     /* output crystal spheres */
  203.     SET_COORD4( center, -0.8, 0.8, 1.00, 0.17 ) ;
  204.     create_spheres( ¢er, txname) ;
  205.  
  206.     /* set up mountain color - grey */
  207.     SET_COORD( obj_color, 0.5, 0.45, 0.35 ) ;
  208.     txname = lib_output_color( &obj_color, 0.2, 0.8, 0.0, 0.0, 0.0, 0.0, 0.0) ;
  209.  
  210.     /* grow mountain */
  211.     num_pts = 1<<SIZE_FACTOR ;
  212.     ratio = 2.0 /
  213.          exp( (double)( log( (double)2.0 ) / (FRACTAL_DIMENSION-1.0) ) ) ;
  214.     roughness = sqrt( (double)( SQR(ratio) - 1.0 ) ) ;
  215.     grow_mountain( num_pts, 0, 0, 0.0, 0.0, 0.0, 0.0, txname) ;
  216. }
  217.